package oop.core.med;

import java.util.*;
import oop.core.entity.*;
import oop.core.item.*;
import oop.core.map.GameMap;
import oop.core.map.Location;
import oop.core.map.MovementType;
import oop.core.visitors.InteractiveItemVisitable;


public class MovementLogic
{
	private GameMap gameMap;

	public MovementLogic(GameMap gameMap) {
		this.gameMap = gameMap;
	}

	public Location move(List<MovementType> movementTypes, Location currentLocation, int direction){

		Location desiredLocation;
		desiredLocation= calcDesiredLocation(currentLocation, direction);

		if(containsInvalidTerrain(desiredLocation, movementTypes)
				|| containsObstacleItem(desiredLocation) || containsInteractiveItem(desiredLocation) || containsEntity(desiredLocation)){
			return null;
		}
		return desiredLocation;
	}


	public Location calcDesiredLocation(Location currentLocation, int direction){
		Location desiredLocation;
		int y = currentLocation.getYPos();
		int x = currentLocation.getXPos();

		//direction: 8 = north, goes ccw as you go down
		switch (direction) {
			case 8:  
				y -= 1;
				break;

			case 9:  
				y -= 1;
				x += 1;
				break;

			case 6:  
				x += 1;
				break;

			case 3:  
				x += 1;
				y += 1;
				break;

			case 2:  
				y += 1;
				break;

			case 1:  
				x -= 1;
				y += 1;
				break;

			case 4:  
				x -= 1;
				break;

			case 7:  
				x -= 1;
				y -= 1;
		}
		desiredLocation = new Location(x,y);
		return desiredLocation;
	}

	private boolean containsInvalidTerrain(Location location, List<MovementType> movementTypes){
		MovementType desiredTerrainMovementType = gameMap.getTerrainAt(location).getTypeMovable();

		for(MovementType t : movementTypes){
			if(desiredTerrainMovementType == t){
				return false;
			}
		}
		return true;  
	}

	//this method isnt needed here
	public boolean containsEntity(Location desiredLocation){
		List<Entity> entities = gameMap.getEntityList();

		for(Entity e : entities){
			if(desiredLocation == e.getLoc()){
				return true;
			}
		}
		return false;  
	}

	private boolean containsObstacleItem(Location desiredLocation){
		ObstacleItem item = gameMap.getObstacleItemAt(desiredLocation);
		if(item == null){
		  return false;
		}	 
		return true;  
	}

	private boolean containsInteractiveItem(Location desiredLocation){
		InteractiveItemVisitable item = gameMap.getInteractiveItemVisitableAt(desiredLocation);
		if(item == null){
		  return false;
		}	 
		return true;  
	}
}

